package com.thememaker.lockstyle;

import com.alibaba.fastjson.JSON;
import com.jfoenix.controls.JFXButton;
import com.thememake.entity.ThemeFileInfo;
import com.thememake.ui.Toast;
import com.thememaker.lockstyle.bean.Lockscreen;
import com.thememaker.lockstyle.bean.Var;
import com.thememaker.lockstyle.bean.ui.*;
import com.thememaker.lockstyle.parsii.ExpressionUtils;
import com.thememaker.util.SVGLoadUtils;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.commons.lang3.Validate;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public class LockStyleCenterLeftEditUtils {

    private ScrollPane leftAnchorPane;
    private ThemeFileInfo themeFileInfo;
    private VBox vBox,addVbox;
    private List<Field> showFieldList;
    private List<Field> canAddFieldList;
    private long lastEditTime = System.currentTimeMillis();
    private Timer timer;
    private ExpressionUtils expressionUtils;
    private LockstyleShowUtils lockstyleShowUtils;
    private boolean showUp = false;

    public LockStyleCenterLeftEditUtils(ScrollPane leftAnchorPane, ThemeFileInfo themeFileInfo) {
        this.leftAnchorPane = leftAnchorPane;
        this.themeFileInfo = themeFileInfo;
        initView();
    }


    private void initView(){
        vBox = new VBox();
        vBox.setSpacing(15);
        vBox.setPadding(new Insets(15));
        addVbox = new VBox();
        addVbox.setSpacing(15);
        addVbox.setPadding(new Insets(15));
    }



    public void updateCenterTextInfo(BaseView baseView, ExpressionUtils expressionUtils, LockstyleShowUtils lockstyleShowUtils) {
        this.expressionUtils = expressionUtils;
        this.lockstyleShowUtils = lockstyleShowUtils;
        vBox.getChildren().clear();
        addVbox.getChildren().clear();
        leftAnchorPane.setContent(vBox);
        initFieldList(baseView);
    }

    private void initFieldList(BaseView baseView){
        if (showFieldList == null){
            showFieldList = new ArrayList<>();
        }
        if (canAddFieldList == null){
            canAddFieldList = new ArrayList<>();
        }
        showFieldList.clear();
        canAddFieldList.clear();
        Field[] fields;
        if (baseView instanceof Lockscreen){
            fields = baseView.getClass().getDeclaredFields();
        }else{
            fields = getAllFields(baseView.getClass());
        }
        //获得Object对象中的所有方法
        for(int i=fields.length-1;i>=0 ;i--){
            Field field = fields[i];
            if (!"layer".equals(field.getName()) && !"groupName".equals(field.getName())
                    &&!"tag".equals(field.getName()) && !"id".equals(field.getName())&&!"visibilityFX".equals(field.getName())){
                    PropertyDescriptor pd = getPropertyDescriptor(field,baseView);
                    Method getMethod = pd.getReadMethod();
                    Object getValue = null;
                    try {
                        getValue = (Object) getMethod.invoke(baseView);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                    if (getValue!=null){
                        if (!(getValue instanceof LinkedHashMap)){
                            showFieldList.add(field);
                            vBox.getChildren().add(initEditItem(baseView,pd,field.getName(),getValue));
                        }
                    }else{
                        canAddFieldList.add(field);
                    }
            }
        }
        if (canAddFieldList.size() > 0){
            HBox hBox = new HBox();
            hBox.setAlignment(Pos.CENTER);
            JFXButton jfxButton = new JFXButton();
            jfxButton.setPrefWidth(400);
            jfxButton.setGraphic(SVGLoadUtils.getInstance().getDownSVG(15,Color.web("#5264AE")));
            jfxButton.setDisableVisualFocus(true);
            jfxButton.setButtonType(JFXButton.ButtonType.FLAT);
            jfxButton.setStyle("-fx-text-fill:#5264AE;-fx-background-color:WHITE;-fx-font-size:14px;");
            jfxButton.setOnAction(event -> {
                if (!showUp){
                    jfxButton.setGraphic(SVGLoadUtils.getInstance().getUpSVG(15,Color.web("#5264AE")));
                    vBox.getChildren().add(addVbox);
                    initAddItem(baseView);
                }else{
                    jfxButton.setGraphic(SVGLoadUtils.getInstance().getDownSVG(15,Color.web("#5264AE")));
                    vBox.getChildren().remove(addVbox);
                }
                showUp = !showUp;

            });
            vBox.getChildren().add(jfxButton);
        }
    }



    private void initAddItem(BaseView baseView){
        addVbox.getChildren().clear();
        for (Field field:canAddFieldList){
            HBox hBox = new HBox();
            hBox.setAlignment(Pos.CENTER);
            JFXButton jfxButton = new JFXButton();
            jfxButton.setDisableVisualFocus(true);
            jfxButton.setGraphic(SVGLoadUtils.getInstance().getAddSVG(15,Color.web("#5264AE")));
            jfxButton.setButtonType(JFXButton.ButtonType.FLAT);
            Label leftLabel = new Label(field.getName());
            leftLabel.setId("diy-fontColor");
            leftLabel.setPrefWidth(150);
            hBox.getChildren().addAll(leftLabel,jfxButton);
            addVbox.getChildren().add(hBox);
            jfxButton.setOnAction(event -> {
                addVbox.getChildren().remove(hBox);
                canAddFieldList.remove(field);
                PropertyDescriptor pd = getPropertyDescriptor(field,baseView);
                vBox.getChildren().add(showFieldList.size(),initEditItem(baseView,pd,field.getName(),null));
                showFieldList.add(field);
            });
        }
    }

    private PropertyDescriptor getPropertyDescriptor(Field field,BaseView baseView){
        PropertyDescriptor pd = null;
        System.err.println("field >>> " + field.getName());
            try {
                if (baseView instanceof Image){
                    pd = new PropertyDescriptor(field.getName(), Image.class);
                }else if (baseView instanceof Group){
                    pd = new PropertyDescriptor(field.getName(), Group.class);
                }else if (baseView instanceof Button){
                    pd = new PropertyDescriptor(field.getName(), Button.class);
                }else if (baseView instanceof Lockscreen){
                    pd = new PropertyDescriptor(field.getName(), Lockscreen.class);
                }else if (baseView instanceof Var){
                    pd = new PropertyDescriptor(field.getName(), Var.class);
                }else if (baseView instanceof Slider){
                    pd = new PropertyDescriptor(field.getName(), Slider.class);
                }else if (baseView instanceof Unlocker){
                    pd = new PropertyDescriptor(field.getName(), Unlocker.class);
                }else if (baseView instanceof Text){
                    pd = new PropertyDescriptor(field.getName(), Text.class);
                }else{
                    pd = new PropertyDescriptor(field.getName(), BaseView.class);
                }
            } catch (IntrospectionException e) {
                e.printStackTrace();
            }
            return pd;
    }

    private HBox initEditItem(BaseView baseView,PropertyDescriptor pd,String name,Object getValue){
        HBox hBox = new HBox();
        hBox.setAlignment(Pos.CENTER_LEFT);
        Label leftLabel = new Label(name + " = ");
        leftLabel.setId("diy-fontColor");
        TextField textField = new TextField();
        textField.setPrefWidth(300);
        textField.setId("diy-textarea");
        HBox.setHgrow(textField, Priority.ALWAYS);
        if (getValue != null){
            if (getValue instanceof String){
                textField.setText(getValue.toString());
            }else{
                textField.setText(JSON.toJSONString(getValue));
            }
        }
        hBox.getChildren().addAll(leftLabel,textField);
        if ("src".equals(name)){
            textField.setEditable(false);
            JFXButton changeSrcButton = new JFXButton();
            changeSrcButton.setDisableVisualFocus(true);
            changeSrcButton.setTooltip(new Tooltip("选择图片"));
            changeSrcButton.setButtonType(JFXButton.ButtonType.FLAT);
            changeSrcButton.setGraphic(SVGLoadUtils.getInstance().getImageSVG(15,Color.web("#5264AE")));
            changeSrcButton.setStyle("-fx-text-fill:#5264AE;-fx-background-color:WHITE;-fx-font-size:14px;");
            hBox.getChildren().add(changeSrcButton);
            changeSrcButton.setOnAction(event -> {
                FileChooser fileChooser = new FileChooser();
                fileChooser.setTitle("选择图片");
                Path lockscreenPath = Paths.get(themeFileInfo.getThemeDir().getPath(), themeFileInfo.getThemeType(), ThemeFileInfo.LOCKSTYLE_NAME, "lockscreen");
                fileChooser.setInitialDirectory(lockscreenPath.toFile());
                File file = fileChooser.showOpenDialog(new Stage());
                if (file != null){
                    if (file.getPath().contains(lockscreenPath.toString())){
                        String srcString = file.getPath().replace(lockscreenPath.toString()+File.separator,"");
                        Image image = (Image)baseView;
                        if (image.getSrcid()!=null){
                            if (srcString.lastIndexOf("_") >=0 ){
                                srcString = srcString.substring(0,srcString.lastIndexOf("_"))+".png";
                                textField.setText(srcString);
                                saveValue(baseView,pd,srcString);
                            }else{
                                Toast.makeText(new Stage(),"请选择 _xx.png 结尾的图片",1000);
                            }
                        }else{
                            textField.setText(srcString);
                            saveValue(baseView,pd,srcString);
                        }
                    }
                }
            });
        }else{
            textField.textProperty().addListener((observable, oldValue, newValue) -> {
                lastEditTime = System.currentTimeMillis();
                if (timer!=null){
                    timer.cancel();
                }
                timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        if (System.currentTimeMillis()-lastEditTime>=2000){
                            Platform.runLater(()->{
                                double parseVale = expressionUtils.parseExpr(newValue);
                                if (parseVale != -9999){
                                    textField.setId("diy-textarea");
                                    System.err.println("更新UI");
                                    saveValue(baseView,pd,newValue);
                                    System.err.println("baseView >>> " + JSON.toJSONString(baseView));
                                    timer.cancel();
                                }else{
                                    textField.setId("textfield-error");
                                }
                            });
                        }else{
                            System.err.println("正在修改，不需要更新");
                        }

                    }
                }, 2000);
            });
        }

        return hBox;
    }

    public void saveValue(BaseView baseView,PropertyDescriptor pd,String value){
        try {
            pd.getWriteMethod().invoke(baseView,value);
            lockstyleShowUtils.updateRightPreview();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }


    public static Field[] getAllFields(final Class<?> cls) {
        final List<Field> allFieldsList = getAllFieldsList(cls);
        return allFieldsList.toArray(new Field[allFieldsList.size()]);
    }

    public static List<Field> getAllFieldsList(final Class<?> cls) {
        Validate.isTrue(cls != null, "The class must not be null");
        final List<Field> allFields = new ArrayList<Field>();
        Class<?> currentClass = cls;
        while (currentClass != null) {
            final Field[] declaredFields = currentClass.getDeclaredFields();
            for ( int i=declaredFields.length-1;i >= 0;i-- ) {
                allFields.add(declaredFields[i]);
            }
            currentClass = currentClass.getSuperclass();
        }
        return allFields;
    }

}
